package com.google.code.jtasks.bugzilla;

import java.util.HashSet;
import java.util.Set;

import com.google.code.jtasks.bugzilla.config.BugzillaRepositoryField;
import com.google.code.jtasks.bugzilla.fields.BugzillaStandardField;
import com.google.code.jtasks.bugzilla.fields.BugzillaStandardResolution;
import com.google.code.jtasks.bugzilla.proxy.bug.BugFieldsProxy.Field;
import com.google.code.jtasks.bugzilla.proxy.bug.BugFieldsProxy.FieldValue;
import com.google.code.jtasks.bugzilla.proxy.bug.BugFieldsProxy.FieldsResult;
import com.google.code.jtasks.model.Priority;
import com.google.code.jtasks.model.Resolution;

/**
 * Stores configuration data for a task repository accessed by a {@link BugzillaTaskSystemAdapter}.
 */
public class BugzillaRepositoryData
{
	private final Set<BugzillaRepositoryField> fields;
	private final Set<Priority> priorities;
	private final Set<Resolution> resolutions;

	/**
	 * Constructs a new {@link BugzillaRepositoryData} from the specified {@link FieldsResult}.
	 * 
	 * @param fieldsResult
	 *            the {@link FieldsResult} instance to build the {@link BugzillaRepositoryData} from
	 */
	public BugzillaRepositoryData(FieldsResult fieldsResult)
	{
		this.fields = buildFields(fieldsResult);
		this.priorities = buildPriorities(fieldsResult);
		this.resolutions = buildResolutions(fieldsResult);
	}

	/**
	 * Extracts the repository's {@link BugzillaRepositoryField}s from the specified {@link FieldsResult}
	 * instance.
	 * 
	 * @param fieldsResult
	 *            the {@link FieldsResult} instance to extract the repository's
	 *            {@link BugzillaRepositoryField}s from
	 * @return the repository's {@link BugzillaRepositoryField}s
	 */
	private static Set<BugzillaRepositoryField> buildFields(FieldsResult fieldsResult)
	{
		Set<BugzillaRepositoryField> repoFields = new HashSet<BugzillaRepositoryField>();

		// Build a BugzillaRepositoryField for each Field in the FieldsResult
		for (Field fieldObject : fieldsResult.getFields())
		{
			String fieldName = fieldObject.getName();
			BugzillaStandardField standardField = BugzillaStandardField.getField(fieldName);

			BugzillaRepositoryField repoField = new BugzillaRepositoryField(standardField, fieldName);
			repoFields.add(repoField);
		}

		return repoFields;
	}

	/**
	 * Extracts the repository's {@link Priority}s from the specified {@link FieldsResult} instance.
	 * 
	 * @param fieldsResult
	 *            the {@link FieldsResult} instance to extract the repository's {@link Priority}s from
	 * @return the repository's {@link Priority}s
	 */
	private static Set<Priority> buildPriorities(FieldsResult fieldsResult)
	{
		Set<Priority> priorities = new HashSet<Priority>();

		// Find the BugzillaStandardField.PRIORITY Field in the FieldsResult
		Field priorityFieldObject = fieldsResult
				.getField(BugzillaStandardField.PRIORITY.getFieldName(), true);

		// Create a BugzillaPriority for each FieldValue in the field
		for (FieldValue priorityValue : priorityFieldObject.getValues())
		{
			String name = priorityValue.getName();
			int sortkey = priorityValue.getSortkey();

			Priority priority = new Priority(sortkey, name);
			priorities.add(priority);
		}

		return priorities;
	}

	/**
	 * Extracts the repository's {@link Resolution}s from the specified {@link FieldsResult} instance.
	 * 
	 * @param fieldsResult
	 *            the {@link FieldsResult} instance to extract the repository's {@link Resolution}s from
	 * @return the repository's {@link Resolution}s
	 */
	private static Set<Resolution> buildResolutions(FieldsResult fieldsResult)
	{
		Set<Resolution> resolutions = new HashSet<Resolution>();

		// Find the BugzillaStandardField.RESOLUTION Field in the FieldsResult
		Field priorityFieldObject = fieldsResult.getField(BugzillaStandardField.RESOLUTION.getFieldName(),
				true);

		// Create a BugzillaResolution for each FieldValue in the field
		for (FieldValue resolutionValue : priorityFieldObject.getValues())
		{
			String name = resolutionValue.getName();
			BugzillaStandardResolution resolutionConstant = BugzillaStandardResolution.getResolution(name);
			boolean resolved = resolutionConstant != null ? resolutionConstant.isResolved() : true;

			Resolution resolution = new Resolution(resolved, name);
			resolutions.add(resolution);
		}

		return resolutions;
	}

	/**
	 * Returns the {@link Priority} that matches the specified {@link Priority#getLabel()}, or
	 * <code>null</code> if no match could be found.
	 * 
	 * @param label
	 *            the {@link Priority#getLabel()} to match against
	 * @return the {@link Priority} that matches the specified {@link Priority#getLabel()}, or
	 *         <code>null</code> if no match could be found
	 */
	public Priority findPriority(String label)
	{
		for (Priority priority : priorities)
			if (priority.getLabel().equals(label))
				return priority;

		return null;
	}

	/**
	 * Returns the {@link Resolution} that matches the specified {@link Resolution#getLabel()}, or
	 * <code>null</code> if no match could be found.
	 * 
	 * @param label
	 *            the {@link Resolution#getLabel()} to match against
	 * @return the {@link Resolution} that matches the specified {@link Resolution#getLabel()}, or
	 *         <code>null</code> if no match could be found
	 */
	public Resolution findResolution(String label)
	{
		for (Resolution resolution : resolutions)
			if (resolution.getLabel().equals(label))
				return resolution;

		return null;
	}
}
